<template>
  <div class="main-container">
    <el-form ref="createForm" :model="dataForm" :rules="rules">
      <!-- 基本配置 -->
      <div class="data-show">
        <!-- 标题 -->
        <div class="data-actions data-title-between">
          <h3>基本配置</h3>
          <div class="data-action-show" v-if="isCreated">
            <i 
              class="iconfont data-action-show-icon" 
              :class="{'icon-arrowcircleup': dataForm.showBasic, 'icon-shezhi': !dataForm.showBasic}"
              @click="dataForm.showBasic = !dataForm.showBasic"
            ></i>
          </div>
        </div>
        <!-- 内容区 -->
        <transition name="upload" mode="out-in">
        <div class="data-table" v-show="dataForm.showBasic">
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <!-- 策略名称 -->
            <div class="common-item item-5">
              <label class="condition-label">策略名称</label>
              <el-form-item class="condition-input" prop="strategyName">
                <el-input type="text" placeholder="请输入策略名称" v-model="dataForm.strategyName" />
              </el-form-item>
            </div>
            <!-- 选择算法平台 -->
            <div class="common-item item-5">
              <label class="condition-label">选择算法平台</label>
              <el-form-item class="condition-input radio-input" prop="system">
                <el-radio v-for="(item, index) in systems" :key="index" :label="item.name" :value="item.id" v-model="dataForm.system">
                  <span>{{ item.name }}</span>
                </el-radio>
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <!-- 基础工作空间文件夹绝对路径 -->
            <div class="common-item item-3">
              <label class="condition-label">
                <el-tooltip :content="desDatas.baseWorkDirAbsPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                基础工作路径
              </label>
              <el-form-item class="condition-input" prop="baseWorkDirAbsPath">
                <el-input type="text" placeholder="请输入基础工作路径" v-model="dataForm.baseWorkDirAbsPath" />
              </el-form-item>
            </div>
            <!-- 沙盒文件夹绝对路径 -->
            <div class="common-item item-3">
              <label class="condition-label">
                <el-tooltip :content="desDatas.sandboxDirAbsPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                沙盒路径
              </label>
              <el-form-item class="condition-input" prop="sandboxDirAbsPath">
                <el-input type="text" placeholder="请输入沙盒路径" v-model="dataForm.sandboxDirAbsPath" />
              </el-form-item>
            </div>
            <!-- 静态链接库文件夹路径 -->
            <div class="common-item item-3">
              <label class="condition-label">
                <el-tooltip :content="desDatas.libDirPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                静态链接库路径
              </label>
              <el-form-item class="condition-input" prop="libDirPath">
                <el-input type="text" placeholder="请输入静态链接库路径" v-model="dataForm.libDirPath" />
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <!-- 可执行脚本文件绝对路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.cmdTemplateFileAbsPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                可执行脚本模版文件绝对路径
              </label>
              <el-form-item class="condition-input" prop="cmdTemplateFileAbsPath">
                <el-input type="text" placeholder="请输入可执行脚本模版文件绝对路径" v-model="dataForm.cmdTemplateFileAbsPath" />
              </el-form-item>
            </div>
            <!-- cmd文件路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.cmdFilePath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                生成可执行脚本文件路径
              </label>
              <el-form-item class="condition-input" prop="cmdFilePath">
                <el-input type="text" placeholder="请输入生成可执行脚本文件路径" v-model="dataForm.cmdFilePath" />
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <!-- 嵌入文件路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.embedFilePath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                嵌入文件路径
              </label>
              <el-form-item class="condition-input" prop="embedFilePath">
                <el-input type="text" placeholder="请输入嵌入文件路径" v-model="dataForm.embedFilePath" />
              </el-form-item>
            </div>
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.extractFilePath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                提取文件路径
              </label>
              <el-form-item class="condition-input" prop="extractFilePath">
                <el-input type="text" placeholder="请输入提取文件路径" v-model="dataForm.extractFilePath" />
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <!-- 配置文件绝对路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.configTemplateFileAbsPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                配置模版文件绝对路径
              </label>
              <el-form-item class="condition-input" prop="configTemplateFileAbsPath">
                <el-input type="text" placeholder="请输入配置模版文件绝对路径" v-model="dataForm.configTemplateFileAbsPath" />
              </el-form-item>
            </div>
            <!-- 配置文件路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.configFilePath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                生成配置文件路径
              </label>
              <el-form-item class="condition-input" prop="configFilePath">
                <el-input type="text" placeholder="请输入生成配置文件路径" v-model="dataForm.configFilePath" />
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <!-- 模块参文件模板绝对路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.moduleParamsTemplateFiileAbsPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                模块参数模板文件绝对路径
              </label>
              <el-form-item class="condition-input" prop="moduleParamsTemplateFiileAbsPath">
                <el-input type="text" placeholder="请输入模块参数模板文件绝对路径" v-model="dataForm.moduleParamsTemplateFiileAbsPath" />
              </el-form-item>
            </div>
            <!-- 模块参数文件路径 -->
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.moduleParamsFiilePath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                生成模块参数文件路径
              </label>
              <el-form-item class="condition-input" prop="moduleParamsFiilePath">
                <el-input type="text" placeholder="请输入生成模块参数文件路径" v-model="dataForm.moduleParamsFiilePath" />
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.staticLinkDirPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                静态链接文件路径
              </label>
              <el-form-item class="condition-input" prop="staticLinkDirPath">
                <el-input type="text" placeholder="请输入静态链接文件路径" v-model="dataForm.staticLinkDirPath" />
              </el-form-item>
            </div>
            <div class="common-item item-5">
              <label class="condition-label">
                <el-tooltip :content="desDatas.dynamicLinkDirPath" placement="top" effect="dark">
                  <i class="iconfont icon-gantanhao2 parameter-des"></i>
                </el-tooltip>
                动态链接文件路径
              </label>
              <el-form-item class="condition-input" prop="dynamicLinkDirPath">
                <el-input type="text" placeholder="请输入动态链接文件路径" v-model="dataForm.dynamicLinkDirPath" />
              </el-form-item>
            </div>
          </div>
          <!-- 通用布局行 -->
          <div class="common-row row-between">
            <div class="common-item item-10" :class="{'item-upload': uploadObj.exampleFileId.showFileList}">
              <label class="condition-label">工程示例上传</label>
              <el-form-item class="condition-input" prop="exampleFileId">
                <el-upload
                  class="upload"
                  :ref="uploadObj.uploadRef('exampleFileId')"
                  drag
                  :action="uploadObj.uploadUrl"
                  :limit="1"
                  :headers="uploadObj.headers"
                  :show-file-list="uploadObj.exampleFileId.showFileList"
                  :before-upload="uploadObj.beforeUpload('exampleFileId')"
                  :on-success="uploadObj.onSuccess('exampleFileId', dataForm)"
                  :on-progress="uploadObj.onProgress('exampleFileId')"
                  :on-error="uploadObj.onError('exampleFileId')"
                  :on-remove="uploadObj.onRemove('exampleFileId')"
                  v-model:file-list="uploadObj.exampleFileId.fileList"
                >
                  <transition name="upload" mode="out-in">
                    <div class="upload-empty" v-if="!dataForm.exampleFileId">
                      <i class="iconfont icon-icon_update upload-icon"></i>
                      <p class="upload-des">拖拽文件至此或点击上传</p>
                    </div>
                    <div class="upload-content" v-else>
                      <i class="iconfont icon-daimawenjian-mian upload-icon"></i>
                      <el-tooltip :content="uploadObj.exampleFileId.fileName" placement="top" :disabled="!uploadObj.exampleFileId.fileName">
                        <p class="upload-des">{{ uploadObj.exampleFileId.fileName }}</p>
                      </el-tooltip>
                    </div>
                  </transition>
                </el-upload>
              </el-form-item>
            </div>
          </div>
        </div>
        </transition>
      </div>
      <!-- 底部的按钮(创建) -->
      <transition name="upload" mode="out-in">
        <div class="btn-groups" v-if="!isCreated">
          <button type="button" class="btn btn-normal" @click="back">取消</button>
          <button type="button" class="btn" @click="handleCreate">创建策略任务</button>
        </div>
      </transition>
      <!-- 步骤流程配置 -->
      <transition name="upload" mode="out-in">
        <div class="data-show" v-if="isCreated">
          <div class="data-actions data-title-between">
            <h3>策略流程配置</h3>
            <div class="data-action-show" v-if="isCreated">
              <i 
                class="iconfont data-action-show-icon" 
                :class="{'icon-arrowcircleup': dataForm.showStep, 'icon-shezhi': !dataForm.showStep}"
                @click="dataForm.showStep = !dataForm.showStep"
              ></i>
            </div>
          </div>
          <transition name="upload" mode="out-in">
            <div class="data-table" v-show="dataForm.showStep">
              <div class="flow-container">
                <VueFlow
                  v-model:nodes="nodes"
                  v-model:edges="edges"
                  :connection-mode="ConnectionMode.Strict"
                >
                  <Panel>
                    <div class="flex-actions-container">
                      <el-tooltip content="添加步骤" placement="top">
                        <i class="iconfont flow-action-btn icon-tianjia2" @click="createNode"></i>
                      </el-tooltip>
                      <el-tooltip content="清除关系" placement="top">
                        <i class="iconfont flow-action-btn icon-qingchu" @click="delAllEdge"></i>
                      </el-tooltip>
                      <el-tooltip content="全部清空" placement="top">
                        <i class="iconfont flow-action-btn icon-quanbushanchu2" @click="clearAll"></i>
                      </el-tooltip>
                    </div>
                  </Panel>
                  <!-- 自定义节点 - step类型 -->
                  <template #node-step="props">
                    <Handle :id="`${props.id}t`" type="target" :position="Position.Top" />
                    <Handle :id="`${props.id}b`" type="source" :position="Position.Bottom" />
                    <div class="inner">
                      <div class="step-name">{{ props.data.name }}</div>
                      <div class="step-actions">
                        <i class="iconfont icon-shezhi5 step-action set" @click="setStep(props)"></i>
                        <i class="iconfont icon-quanbushanchu6 step-action del" @click="delStep(props)"></i>
                      </div>
                      <div class="step-options" v-if="props.data.algoExecStrategyOpts.length > 0">
                        <div class="step-option-item" :class="{end: opt.isEnd}" :id="`${props.id}opt${index}`" v-for="(opt, index) in props.data.algoExecStrategyOpts">{{ opt.optName }}</div>
                      </div>
                      <div class="step-actions step-actions-scroll" v-if="props.data.algoExecStrategyOpts.length > 5">
                        <i class="iconfont icon-shang1 step-action set" @click="intoViewTop(props)"></i>
                        <i class="iconfont icon-xia1 step-action set" @click="intoViewBottom(props)"></i>
                      </div>
                    </div>
                  </template>
                  <!-- 自定义节点 - start类型 -->
                  <template #node-start="props">
                    <Handle :id="`${props.id}b`" type="source" :position="Position.Bottom" />
                    <div class="inner">
                      <div class="step-name">{{ props.data.name }}</div>
                      <div class="step-actions">
                        <i class="iconfont icon-shezhi5 step-action set" @click="setStep(props)"></i>
                        <i class="iconfont icon-quanbushanchu6 step-action del" @click="delStep(props)"></i>
                      </div>
                      <div class="step-options" v-if="props.data.algoExecStrategyOpts.length > 0">
                        <div class="step-option-item" :class="{end: opt.isEnd}" :id="`${props.id}opt${index}`" v-for="(opt, index) in props.data.algoExecStrategyOpts">{{ opt.optName }}</div>
                      </div>
                      <div class="step-actions step-actions-scroll" v-if="props.data.algoExecStrategyOpts.length >= 5">
                        <i class="iconfont icon-shang1 step-action set" @click="intoViewTop(props)"></i>
                        <i class="iconfont icon-xia1 step-action set" @click="intoViewBottom(props)"></i>
                      </div>
                    </div>
                  </template>
                  <!-- 自定义节点 - end类型 -->
                  <template #node-end="props">
                    <Handle :id="`${props.id}t`" type="target" :position="Position.Top" />
                    <div class="inner">
                      <div class="step-name">{{ props.data.name }}</div>
                      <div class="step-actions">
                        <i class="iconfont icon-shezhi5 step-action set" @click="setStep(props)"></i>
                        <i class="iconfont icon-quanbushanchu6 step-action del" @click="delStep(props)"></i>
                      </div>
                      <div class="step-options" v-if="props.data.algoExecStrategyOpts.length > 0">
                        <div class="step-option-item" :id="`${props.id}opt${index}`" v-for="(opt, index) in props.data.algoExecStrategyOpts">{{ opt.optName }}</div>
                      </div>
                      <div class="step-actions step-actions-scroll" v-if="props.data.algoExecStrategyOpts.length >= 5">
                        <i class="iconfont icon-shang1 step-action set" @click="intoViewTop(props)"></i>
                        <i class="iconfont icon-xia1 step-action set" @click="intoViewBottom(props)"></i>
                      </div>
                    </div>
                  </template>
                  <Background
                    variant="lines"
                    :gap="50"
                    :patternColor="flowPatternColor"
                    :bgColor="flowBgColor"
                  />
                  <Controls @click.prevent="preventUpdatePage"/>
                </VueFlow>
              </div>
            </div>
          </transition>  
        </div>
      </transition>
      
      <!-- 模块库配置 -->
      <transition name="upload" mode="out-in">
        <div class="data-show" v-if="isCreated">
          <div class="data-actions data-title-between">
            <h3>模块库配置</h3>
            <div class="data-action-show">
              <span class="aniTxtBtn action" @click="addModuleLib">添加配置</span>
              <i 
                class="iconfont data-action-show-icon" 
                :class="{'icon-arrowcircleup': dataForm.showModuleLib, 'icon-shezhi': !dataForm.showModuleLib}"
                @click="dataForm.showModuleLib = !dataForm.showModuleLib"
              ></i>
            </div>
          </div>
          <transition name="upload" mode="out-in">
            <div class="data-table moduleLib-container" v-show="dataForm.showModuleLib">
              <transition name="upload" mode="out-in">
                <div class="moduleLib-empty" v-if="dataForm.algoExecStrategyModuleLibs.length < 1">
                  <i class="iconfont icon-wushuju1 data-empty-icon"></i>
                  <h3 class="data-empty">未设置模块库请添加</h3>
                </div>
                <div v-else>
                  <transition-group name="list">
                    <div class="module-item" v-for="(item, index) in dataForm.algoExecStrategyModuleLibs" :key="item.key">
                      <el-form :ref="bindModuleLibRef(item, index)" :model="item" :rules="item.rules">
                        <span class="module-item-title">模块库{{ index + 1 }}</span>
                        <span class="module-item-del" @click="handleDelModuleLib(item, index)">删除</span>
                        <div class="common-row row-between">
                          <div class="parameter-form-item item-5">
                            <label class="condition-label">模块库</label>
                            <el-form-item class="condition-input" prop="moduleLibId">
                              <el-cascader
                                clearable 
                                v-model="item.moduleLibId" 
                                :options="moduleLibDatas"
                                :props="{
                                  value: 'id',
                                  label: 'name',
                                  children: 'children',
                                  checkStrictly: true
                                }" 
                                @change="selectModuleLibs(item, $event)"
                                @visible-change="cascaderVisibleChange"
                              />
                              <!--测试-->
                              <!-- <el-select v-model="item.optIdSelect" clearable multiple>
                                  <el-option v-for="(opt, optInd) in stepOptions" :key="optInd" :label="opt.name" :value="opt.id"></el-option>
                                </el-select> -->
                            </el-form-item>
                          </div>
                          <div class="parameter-form-item item-5">
                            <label class="condition-label">是否关联选项</label>
                            <el-form-item class="condition-input radio-input" prop="isRelateOpt">
                              <el-radio @change="isRelateChange(item, index)" v-for="(it, ind) in moduleLibRelates" :key="ind" :label="it.label" :value="it.value" v-model="item.isRelateOpt">
                              </el-radio>
                            </el-form-item>
                          </div>
                          <!-- <transition name="upload">
                            <div class="parameter-form-item item-5" v-show="item.isRelateOpt == 1">
                              <label class="condition-label">关联选项</label>
                              <el-form-item class="condition-input radio-input" prop="relateOptId">
                                <el-cascader
                                  clearable 
                                  v-model="item.optIdSelect" 
                                  :options="stepOptions"
                                  :props="{
                                    value: 'id',
                                    label: 'name',
                                    children: 'children',
                                    // checkStrictly: true,
                                    multiple: true
                                  }" 
                                  collapse-tags
                                  collapse-tags-tooltip
                                  @change="moduleLibSelectOptId(item, $event)"
                                  @visible-change="cascaderVisibleChange"
                                />
                              </el-form-item>
                            </div>
                          </transition> -->
                        </div>
                        <transition name="upload">
                          <div class="common-row row-between" v-show="item.isRelateOpt == 1">
                            <div class="parameter-form-item item-5">
                              <label class="condition-label">关联步骤</label>
                              <el-form-item class="condition-input radio-input" prop="relateStepId">
                                <el-select
                                  v-model="item.relateStepId"
                                  placeholder="请选择关联的步骤"
                                  clearable
                                  multiple
                                  collapse-tags
                                  collapse-tags-tooltip
                                  @change="moduleLibSelectStepId(item, $event)"
                                >
                                  <el-option v-for="(step, stepIndex) in stepOptions" :key="stepIndex" :label="step.name" :value="step.id" />
                                </el-select>
                              </el-form-item>
                            </div>
                            <div class="parameter-form-item item-5">
                              <label class="condition-label">关联选项</label>
                              <el-form-item class="condition-input radio-input" prop="relateOptId">
                                <el-select
                                  v-model="item.optIdSelect"
                                  placeholder="请选择关联的选项"
                                  clearable
                                  multiple
                                  collapse-tags
                                  collapse-tags-tooltip
                                  no-data-text="请先选择关联步骤"
                                  @change="moduleLibSelectOptId(item, 'relateOptId',$event)"
                                >
                                  <el-option-group
                                    v-for="(step, stepInd) in item.optsOfStep"
                                    :key="stepInd"
                                    :label="step.name"
                                  > 
                                    <el-option v-for="(opt, optInd) in step.children" :key="optInd" :label="opt.name" :value="opt.id" />
                                  </el-option-group>
                                </el-select>
                              </el-form-item>
                            </div>
                          </div>
                        </transition>
                      </el-form>
                    </div>
                  </transition-group>
                </div>
              </transition>
            </div>
          </transition>
        </div>
      </transition>
      <!-- 参数配置 -->
      <transition name="upload" mode="out-in">
        <div class="data-show" v-if="isCreated">
          <div class="data-actions data-title-between">
            <h3>参数配置</h3>
            <div class="data-action-show" v-if="isCreated">
              <span class="aniTxtBtn action" @click="addParams">添加配置</span>
              <i 
                class="iconfont data-action-show-icon" 
                :class="{'icon-arrowcircleup': dataForm.showParams, 'icon-shezhi': !dataForm.showParams}"
                @click="dataForm.showParams = !dataForm.showParams"
              ></i>
            </div>
          </div>
          <transition name="upload" mode="out-in">
            <div class="data-table moduleLib-container" v-show="dataForm.showParams">
              <transition name="upload" mode="out-in">
                <div class="moduleLib-empty" v-if="dataForm.algoExecStrategyParams.length < 1">
                  <i class="iconfont icon-wushuju1 data-empty-icon"></i>
                  <h3 class="data-empty">未设置参数请添加</h3>
                </div>
                <div v-else>
                  <transition-group name="list">
                    <div class="module-item" v-for="(item, index) in dataForm.algoExecStrategyParams" :key="item.key">
                      <el-form :ref="bindModuleLibRef(item, index)" :model="item" :rules="item.rules">
                        <span class="module-item-title">参数{{ index + 1 }}</span>
                        <span class="module-item-del" @click="handleDelParams(item, index)">删除</span>
                        <div class="common-row row-between">
                          <div class="parameter-form-item item-3">
                            <label class="condition-label">参数来源</label>
                            <el-form-item class="condition-input radio-input" prop="paramsSource">
                              <el-radio @change="paramsSourceChange(item, index)" v-for="(it, ind) in paramsSources" :key="ind" :label="it.label" :value="it.value" v-model="item.paramsSource">
                              </el-radio>
                            </el-form-item>
                          </div>
                          <transition name="upload">
                            <div class="parameter-form-item item-3" v-show="item.paramsSource === 0">
                              <label class="condition-label">关联步骤</label>
                              <el-form-item class="condition-input radio-input" prop="relateStepId">
                                <el-select
                                  v-model="item.relateStepId"
                                  placeholder="请选择关联的步骤"
                                  clearable
                                  multiple
                                  collapse-tags
                                  collapse-tags-tooltip
                                  @change="moduleLibSelectStepId(item, $event)"
                                >
                                  <el-option v-for="(step, stepIndex) in stepOptions" :key="stepIndex" :label="step.name" :value="step.id" />
                                </el-select>
                              </el-form-item>
                            </div>
                          </transition>
                          <transition name="upload">
                            <div class="parameter-form-item item-3" v-show="item.paramsSource === 0">
                              <label class="condition-label">关联选项</label>
                              <el-form-item class="condition-input radio-input" prop="paramsSourceOptId">
                                <el-select
                                  v-model="item.optIdSelect"
                                  placeholder="请选择关联的选项"
                                  clearable
                                  multiple
                                  collapse-tags
                                  collapse-tags-tooltip
                                  no-data-text="请先选择关联步骤"
                                  @change="moduleLibSelectOptId(item, 'paramsSourceOptId', $event)"
                                >
                                  <el-option-group
                                    v-for="(step, stepInd) in item.optsOfStep"
                                    :key="stepInd"
                                    :label="step.name"
                                  > 
                                    <el-option v-for="(opt, optInd) in step.children" :key="optInd" :label="opt.name" :value="opt.id" />
                                  </el-option-group>
                                </el-select>
                              </el-form-item>
                            </div>
                          </transition>


                          <!-- <transition name="upload">
                            <div class="parameter-form-item item-5" v-show="item.paramsSource === 0">
                              <label class="condition-label">关联选项</label>
                              <el-form-item class="condition-input radio-input" prop="paramsSourceOptId">
                                <el-cascader
                                  clearable 
                                  v-model="item.optIdSelect" 
                                  :options="stepOptions"
                                  :props="{
                                    value: 'id',
                                    label: 'name',
                                    children: 'children',
                                    // checkStrictly: true,
                                    multiple: true
                                  }" 
                                  collapse-tags
                                  collapse-tags-tooltip
                                  @change="paramsSelectOptId(item, $event)"
                                  @visible-change="cascaderVisibleChange"
                                />
                              </el-form-item>
                            </div>
                          </transition> -->
                        </div>
                        <div class="common-row row-between">
                          <div class="parameter-form-item item-5">
                            <label class="condition-label">参数编码</label>
                            <el-form-item class="condition-input radio-input" prop="paramsCode">
                              <el-input type="text" v-model="item.paramsCode" placeholder="请输入参数编码" />
                            </el-form-item>
                          </div>
                          <div class="parameter-form-item item-5">
                            <label class="condition-label">参数类型</label>
                            <el-form-item class="condition-input radio-input" prop="paramsType">
                              <el-radio v-for="(it, ind) in paramsTypes" :key="ind" :label="it.label" :value="it.value" v-model="item.paramsType">
                              </el-radio>
                            </el-form-item>
                          </div>
                          <div class="parameter-form-item item-5">
                            <label class="condition-label">参数值</label>
                            <el-form-item class="condition-input radio-input" prop="paramsValue">
                              <el-input type="text" v-model="item.paramsValue" placeholder="请输入参数值" />
                            </el-form-item>
                          </div>
                        </div>
                      </el-form>
                    </div>
                  </transition-group>
                </div>
              </transition>
            </div>
          </transition>
        </div>
      </transition>
      <!-- 底部的按钮(更新) -->
      <transition name="upload" mode="out-in">
        <div class="btn-groups" v-if="isCreated">
          <button type="button" class="btn btn-normal" @click="back">取消</button>
          <button type="button" class="btn" @click="handleUpdate">保存策略配置</button>
        </div>
      </transition>
    </el-form>
    <!-- 步骤弹框 -->
    <Dialoger
      width="55%"
      :title="nodeDialoger.title"
      :visible="nodeDialoger.flag"
      @confirm="handleNode"
      @cancel="handleNodeCancel"
    >
      <el-form ref="nodeDiaForm" label-width="100" :model="nodeDialoger.node.data" :rules="nodeDialoger.rules">
        <el-form-item label="步骤名称" class="condition-input dialoger-input" prop="name">
          <el-input v-model="nodeDialoger.node.data.name" placeholder="请输入步骤名称" />
        </el-form-item>
        <el-form-item label="步骤类型" class="condition-input dialoger-input radio-input" prop="type">
          <el-radio @change="changeStepType" v-for="(item, index) in nodeTypes" :key="index" :label="item.label" :value="item.value" v-model="nodeDialoger.node.data.type">
            <span>{{ item.label }}</span>
          </el-radio>
        </el-form-item>
        <el-form-item label="步骤描述" class="condition-input dialoger-input" prop="description">
          <el-input v-model="nodeDialoger.node.data.description" maxlength="100" type="textarea" show-word-limit rows="4" resize="none" placeholder="请输入步骤描述" />
        </el-form-item>
        <el-form-item label="生成选项" class="condition-input dialoger-input">
          <el-input 
            v-model="nodeDialoger.node.data.optionInput" 
            placeholder="请输入选项名称并回车确认" 
            @keyup.enter.native="createStepOption(nodeDialoger.node.data.optionInput)"
            @change="createStepOption(nodeDialoger.node.data.optionInput)"
          />
        </el-form-item>
        <div class="data-list-content">
          <transition name="upload" mode="out-in">
            <div class="data-list-content-inner" v-if="nodeDialoger.node.data.algoExecStrategyOpts.length > 0">
              <transition-group name="list">
                <div 
                  class="option-item" 
                  v-for="(item, index) in nodeDialoger.node.data.algoExecStrategyOpts"
                  :key="item.id"
                >
                  <!-- <el-tooltip content="选项名称" :show-after="800" placement="top">
                    <div class="option-name">
                      <el-input v-model="item.optName" placeholder="选项名称不能为空" />
                    </div>
                  </el-tooltip>
                  <el-tooltip content="选项排序" :show-after="800" placement="top">
                    <div class="option-sort">
                      <el-input-number v-model="item.optSort" :min="0" controls-position="right" />
                    </div>
                  </el-tooltip>
                  <el-tooltip content="选择该选项是否结束流程" :show-after="800" placement="top">
                    <div class="option-end">
                      <el-checkbox v-model="item.isEnd" :true-value="1" :false-value="0" />
                    </div>
                  </el-tooltip> -->
                  <!-- change -->
                   <el-tooltip content="选择该选项是否结束流程" :show-after="800" placement="top">
                    <div class="option-end">
                      <el-checkbox v-model="item.isEnd" :true-value="1" :false-value="0" />
                    </div>
                  </el-tooltip>
                   <el-tooltip content="选项名称" :show-after="800" placement="top">
                    <div class="option-name">
                      <el-input v-model="item.optName" placeholder="选项名称不能为空" />
                    </div>
                  </el-tooltip>
                  <el-tooltip content="选项排序" :show-after="800" placement="top">
                    <div class="option-sort">
                      <el-input-number v-model="item.optSort" :min="0" controls-position="right" />
                    </div>
                  </el-tooltip>
                  <el-tooltip content="选项描述" :show-after="800" placement="top">
                    <div class="option-desc">
                      <el-input v-model="item.optDesc" placeholder="对选项进行说明描述" />
                    </div>
                  </el-tooltip>
                  <i class="iconfont icon-shanchu2 option-close" @click="delOption(item, index)"></i>
                </div>
              </transition-group>
            </div>
            <div class="data-list-content-empty" v-else>
              <i class="iconfont icon-wushuju1 data-list-content-empty-icon"></i>
              <h3 class="data-empty data-list-content-empty-text">暂无选项</h3>
            </div>
          </transition>
        </div>
      </el-form>
    </Dialoger>
    <!-- 关系弹框 -->
    <Dialoger
      :title="edgeDialoger.title"
      :visible="edgeDialoger.flag"
      :other-btn="edgeDialoger.otherBtn"
      width="50%"
      @confirm="handleEdge"
      @cancel="handleEdgeCancel"
      @other="delCurrentEdge"
    >
      <div class="common-row row-around">
        <div class="show-item item-5">
          <label class="show-label">源步骤</label>
          <h4 class="show-content">{{ edgeDialoger.edge.sourceNode.data.name }}</h4>
        </div>
        <div class="show-item item-5">
          <label class="show-label">目标步骤</label>
          <h4 class="show-content">{{ edgeDialoger.edge.targetNode.data.name }}</h4>
        </div>
      </div>
      <!-- 配置关系列表 -->
      <div class="edge-set">
        <transition name="upload">
          <div class="relations edge-relations" v-show="edgeDialoger.edge.data.condition.length > 0">
            <el-radio class="relation-item" v-for="(item, index) in relations" :key="index" :label="item.label" :value="item.value" v-model="edgeDialoger.edge.data.relation" />
          </div>
        </transition>
        <span class="edge-add" @click="addCondition">添加</span>
        <transition name="upload" mode="out-in">
          <div class="condition-empty" v-if="edgeDialoger.edge.data.condition.length < 1">
            <i class="iconfont icon-wushuju1 data-empty-icon"></i>
            <h3 class="data-empty">未设置关系请添加</h3>
          </div>
          <div class="constions-outer" v-else>
            <transition-group name="list">
              <Relation 
                v-for="(item, index) in edgeDialoger.edge.data.condition"
                :key="item.key"
                :condition-item="item"
                :nodes="nodes"
                :opacity="10"
                @change-condition-item="changeConditionItem(item, $event)"
                @operator-change="changeConditionItemOper(item, $event)"
                @change-condition-item-relation="changeConditionItemRelation(item, $event)"
                @del-condition-item="delConditionItem(index)"
              />
            </transition-group>
          </div>
        </transition>
      </div>
    </Dialoger>
  </div>
</template>
<script setup>
import useUserStore from '@/stores/user';
import useAppStore from '@/stores/app';
import Dialoger from '@/components/common/Dialoger.vue';
import Relation from '@/components/Relation.vue';
import { ref, reactive, computed, watch, onMounted, nextTick } from 'vue';
import { api, global } from '@/utils/status';
import { deepCopy } from '@/utils/utils.js';
import { ElMessage, ElMessageBox } from 'element-plus';
import { useRouter, useRoute } from 'vue-router';
import {
  // 新建执行策略
  createStrategy,
  // 更新执行策略
  updateStrategy,
  // 获取执行策略详情
  getStrategyDetail,
  // id生成器
  createId
} from '@/api/strategy.js';
import { 
  VueFlow, 
  ConnectionMode, 
  Panel, 
  Handle, 
  Position, 
  MarkerType,
  useVueFlow,
  // 工具
  getConnectedEdges
} from '@vue-flow/core';
import { Background } from '@vue-flow/background';
import { Controls } from '@vue-flow/controls';
import { getToken } from '@/utils/storage';
import '@vue-flow/controls/dist/style.css';
import * as moduleLibApi from '@/api/moduleLib.js';
import * as rule from '@/utils/rules.js';
import * as fileApi from '@/api/file';

// ============> datas
let styles = getComputedStyle(document.documentElement);
const flowPatternColor = styles.getPropertyValue('--color-main-3').trim();
const flowBgColor = styles.getPropertyValue('--color-gray-2').trim();
const mainColor = styles.getPropertyValue('--color-main').trim();
styles = null;
// 默认步骤节点
const defaultNode = {
  id: null,
  type: api.strategy.nodeType.STEP,
  position: {
    x: 50,
    y: 50
  },
  selectable: false,
  data: {}
};
// 默认步骤节点数据
const defaultStepData = {
  id: null,
  strategyId: null,
  name: '',
  description: '',
  type: null,
  positionX: '',
  posiitonY: '',
  currentIndex: 0,
  algoExecStrategyOpts: [],
  // 添加选项输入绑定值
  optionInput: ''
};
// 默认选项
const defaultOption = {
  id: null,
  eventId: null,
  optName: '',
  optSort: 0,
  optDesc: '',
  isEnd: api.strategy.ends.FALSE
}
// 默认边关系
const defaultEdge = {
  id: null,
  type: 'smoothstep',
  animated: false,
  source: null,
  target: null,
  sourceNode: null,
  targetNode: null,
  interactionWidth: 40,
  markerEnd: {
    type: MarkerType.ArrowClosed,
    color: mainColor
  },
  data: {}
};
// 默认边数据
const defaultEdgeData = {
  id: null,
  strategyId: null,
  sourceRefId: null,
  targetRefId: null,
  relation: null,
  condition: []
};
// 默认边的condition对象
const defaultCondition = {
  key: null,
  relation: null,
  // 描述选项的关系
  operator: null,
  // 选择的步骤id
  propId: null,
  // 指定绑定的步骤选项的key(默认id)
  prop: 'id',
  // 指定绑定的步骤选项的value(默认id)
  value: null,
  condition: []
}
// 默认的模块库项对象
const defaultModuleLib = {
  id: null,
  key: null,
  strategyId: null,
  moduleLibId: null,
  isRelateOpt: null,
  // 关联选项id
  relateOptId: '',
  // 非提交-关联步骤id绑定
  relateStepId: [],
  // 选择步骤筛选出的对应选项数组
  optsOfStep: [],
  // 选择关联选项绑定
  optIdSelect: [],
  formRef: null,
  rules: {
    moduleLibId: rule.createRequiredRule('请选择对应的模块库'),
    isRelateOpt: rule.createRequiredRule('请选择是否关联选项')
  }
}
// 默认的参数对象
const defaultParams = {
  id: null,
  key: null,
  strategyId: null,
  // 参数编码
  paramsCode: '',
  // 参数类型
  paramsType: 0,
  // 参数值
  paramsValue: '',
  // 参数来源
  paramsSource: null,
  // ==========>参数关联选项
  paramsSourceOptId: '',
  // 非提交-关联步骤id绑定
  relateStepId: [],
  // 选择步骤筛选出的对应选项数组
  optsOfStep: [],
  // 选择关联选项绑定
  optIdSelect: [],
  formRef: null,
  rules: {
    paramsSource: rule.createRequiredRule('请选择参数源'),
    paramsCode: rule.createRequiredRule('请输入参数编码'),
    paramsType: rule.createRequiredRule('请选择参数类型'),
    paramsValue: rule.createRequiredRule('请输入参数值')
  }
};

// 算法平台
const systems = ref(api.common.systems);
// 步骤关系描述(外层)
const relations = api.strategy.relations;
// 选择的步骤类型(表单)
const nodeTypes = api.strategy.nodeTypes;
// 是否关联选项数组
const moduleLibRelates = api.module.parameter.relates;
const paramsSources = api.strategy.paramsSources;
const paramsTypes = api.strategy.paramsTypes;
const appStore = useAppStore();
const userStore = useUserStore();
const router = useRouter();
const route = useRoute();
const createForm = ref(null);
const nodeDiaForm = ref(null);
// vueflow实例
const instance = useVueFlow();
const desDatas = {
  // 基础工作空间文件夹绝对路径
  baseWorkDirAbsPath: '编译时需要依赖的文件夹绝对路径',
  // 沙盒文件夹绝对路径
  sandboxDirAbsPath: '沙盒文件夹绝对路径，组合生成时会将会从“基础工作路径”复制到“沙盒路径+组合生成ID”文件夹中',
  // 静态链接库文件夹路径
  libDirPath: '静态链接库文件夹在生成后文件夹的相对路径，静态文件将下载到该文件夹中',
  // cmd文件绝对路径
  cmdTemplateFileAbsPath: '算法组合生成运行脚本模板文件(.vm文件)的绝对路径',
  // cmd文件路径
  cmdFilePath: '算法组合生成运行脚本文件的相对路径，平台将根据“可执行脚本模板文件”生成“可执行脚本文件”',
  // 嵌入文件路径
  embedFilePath: '可执行脚本文件编译、链接完成后，生成的嵌入程序文件的相对路径，将根据此路径判断算法执行是否成功',
  // 提取文件路径
  extractFilePath: '可执行脚本文件编译、链接完成后，生成的提取程序文件的相对路径，将根据此路径判断算法执行是否成功',
  // 配置文件绝对路径
  configTemplateFileAbsPath: '算法组合生成运行脚本所需配置文件模板文件(.vm文件)的绝对路径',
  // 配置文件路径
  configFilePath: '算法组合生成运行脚本所需配置文件的相对路径，平台将根据“配置模板文件”生成“配置文件”',
  // 模块参文件模板绝对路径
  moduleParamsTemplateFiileAbsPath: '算法组合生成运行所需模块参数模板文件(.vm文件)的绝对路径',
  // 模块参数文件路径
  moduleParamsFiilePath: '算法组合生成运行脚本所需模块参数文件的相对路径，平台将根据“参数模板文件”生成“参数文件”',
  // 静态链接文件路径
  staticLinkDirPath: '可执行脚本文件编译、链接完成后，生成的静态链接文件夹的相对路径',
  // 动态链接文件路径
  dynamicLinkDirPath: '可执行脚本文件编译、链接完成后，生成的动态链接文件夹的相对路径',
};
// 主数据对象
const dataForm = ref({
  createFlag: false,
  updateFlag: false,
  showBasic: true,
  showStep: true,
  showModuleLib: true,
  showParams: true,
  id: null,
  // id: '2',
  strategyName: '',
  system: null,
  // 基础工作空间文件夹绝对路径
  baseWorkDirAbsPath: '',
  // 沙盒文件夹绝对路径
  sandboxDirAbsPath: '',
  // 静态链接库文件夹路径
  libDirPath: '',
  // cmd文件绝对路径
  cmdTemplateFileAbsPath: '',
  // cmd文件路径
  cmdFilePath: '',
  // 嵌入文件路径
  embedFilePath: '',
  // 提取文件路径
  extractFilePath: '',
  // 配置文件绝对路径
  configTemplateFileAbsPath: '',
  // 配置文件路径
  configFilePath: '',
  // 模块参文件模板绝对路径
  moduleParamsTemplateFiileAbsPath: '',
  // 模块参数文件路径
  moduleParamsFiilePath: '',
  staticLinkDirPath: '',
  dynamicLinkDirPath: '',
  // 工程示例文件上传
  exampleFileId: '',
  // 步骤数组
  algoExecStrategyEvents: [],
  // 步骤关系数组
  algoExecStrategySequenceFlows: [],
  // 关联模块库数组
  algoExecStrategyModuleLibs: [],
  // 关联参数数组
  algoExecStrategyParams: []
});
const nodes = ref([]);
const edges = ref([]);
const moduleLibDatas = ref([]);
// const moduleLibDatas = [];
// 节点弹框控制对象
const nodeDialoger = ref({
  rules: {
    name: rule.createRequiredRule('步骤名称不能为空'),
    type: rule.createRequiredRule('请选择步骤类型')
  },
  title: '添加步骤',
  flag: false,
  node: null
});
// 边弹框控制对象
const edgeDialoger = ref({
  rules: {},
  title: '添加关系',
  otherBtn: {
    show: false,
    text: '删除当前关系'
  },
  flag: false,
  edge: null
});
// 上传对象
const uploadObj = ref({
  url: `${import.meta.env.VITE_FILE_BASE_API}${fileApi.uploadUrl}`,
  uploadUrl: `${import.meta.env.VITE_FILE_BASE_API}${fileApi.uploadUrl}`,
  headers: {},
  uploadRef(key){
    return function (dom){
      if (dom){
        uploadObj.value[key].dom = dom;
      }
    }
  },
  beforeUpload(key, limit = api.upload.commonSizeLimit){
    return function (file){
      if (uploadObj.value[key].uploading){
        ElMessage.warning('当前有文件正在上传，请稍后重试');
        return false;
      }
      let extension = (file.size < limit) && (file.size > 0);
      if (!extension) {
        ElMessage.warning(`上传文件不符合大小限制，文件须小于${limit / (1024 * 1024)}M 且大于 0`);
        return extension;
      }
      // todo - 这里做文件扩展名的校验
      let fileType = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
      extension = fileType == 'zip' || fileType == '7z' || fileType == 'rar' ? true : false;
      if (!extension){
        ElMessage.warning('上传文件须为 lib / a / h 文件!');
      }
      uploadObj.value[key].fileName = extension ? file.name : '';
      uploadObj.value[key].showFileList = true;
      return extension;
    }
  },
  onProgress(key){
    return function (e){
      uploadObj.value[key].showFileList = true;
      uploadObj.value[key].uploading = true;
    }
  },
  onSuccess(key, data){
    return function (e){
      uploadObj.value[key].showFileList = false;
      uploadObj.value[key].uploading = false;
      if (e.code === api.code.SUCCESS){
        uploadObj.value[key].dom.clearFiles();
        ElMessage.success('上传成功');
        uploadObj.value[key].fileName = e.data.fileName;
        if (data[key]){
          fileApi.delFile({fileId: data[key]})
        }
        data[key] = e.data.id;
      } else {
        let msg = e.msg || e.message || '上传失败，请稍后重试或联系管理员';
        ElMessage({
          type: 'error',
          duration: 1500,
          message: msg
        });
      }
    }
  },
  onError(key){
    return function (e){
      let message = e.msg || e.message || '上传失败，请稍后重试或联系管理员';
      ElMessage({
        type: 'error',
        duration: 1500,
        message
      });
      uploadObj.value[key].showFileList = false;
      uploadObj.value[key].uploading = false;
      uploadObj.value[key].dom.clearFiles();
      uploadObj.value[key].fileName = '';
    }
  },
  onRemove(key){
    return function (e){
      uploadObj.value[key].showFileList = false;
      uploadObj.value[key].uploading = false;
      uploadObj.value[key].dom.clearFiles();
      uploadObj.value[key].fileName = '';
    }
  },
  exampleFileId: {
    dom: null,
    showFileList: false,
    fileName: '',
    uploading: false
  }
});
uploadObj.value.headers['Authorization'] = userStore.token ? userStore.token : getToken();
const rules = ref({
  strategyName: rule.createRequiredRule('策略名称不能为空'),
  system: rule.createRequiredRule('算法平台不能为空'),
  baseWorkDirAbsPath: rule.createRequiredRule('基础工作空间路径不能为空'),
  sandboxDirAbsPath: rule.createRequiredRule('沙盒文件夹路径不能为空'),
  libDirPath: rule.createRequiredRule('静态链接库文件夹路径不能为空'),
  cmdTemplateFileAbsPath: rule.createRequiredRule('可执行脚本模版文件绝对路径不能为空'),
  cmdFilePath: rule.createRequiredRule('生成可执行脚本文件路径不能为空'),
  embedFilePath: rule.createRequiredRule('嵌入文件路径不能为空'),
  extractFilePath: rule.createRequiredRule('提取文件路径不能为空'),
  configTemplateFileAbsPath: [{
    validator(rule, value, callback){
      if (dataForm.value.configFilePath && !value){
        callback(new Error('请同时输入配置模版文件绝对路径和生成配置文件路径'));
      } else {
        callback();
      }
    },
    // todo - 这里要把下面的四个同类型验证抽取出来
    // validator: specialValidator(dataForm.value.configFilePath, '请同时输入配置文件绝对路径和配置文件路径'),
    trigger: ['blur', 'change']
  }],
  configFilePath: [{
    validator(rule, value, callback){
      if (dataForm.value.configTemplateFileAbsPath && !value){
        callback(new Error('请同时输入配置模版文件绝对路径和生成配置文件路径'));
      } else {
        callback();
      }
    },
    trigger: ['blur', 'change']
  }],
  moduleParamsTemplateFiileAbsPath: [{
    validator(rule, value, callback){
      if (dataForm.value.moduleParamsFiilePath && !value){
        callback(new Error('请同时输入模块参数模板文件绝对路径和生成模块参数文件路径'));
      } else {
        callback();
      }
    },
    trigger: ['blur', 'change']
  }],
  moduleParamsFiilePath: [{
    validator(rule, value, callback){
      if (dataForm.value.moduleParamsTemplateFiileAbsPath && !value){
        callback(new Error('请同时输入模块参数模板文件绝对路径和生成模块参数文件路径'));
      } else {
        callback();
      }
    },
    trigger: ['blur', 'change']
  }]
});

// ============> computed
const isCreated = computed(() => {
  return dataForm.value.id ? true: false;
})

// ============> hooks
getModuleLibs();
if (route.query && route.query.id){
  init();
}
// ============> utils
// 抽取公共的特殊校验函数
// function specialValidator(validValue, warning){
//   return function (rule, value, callback){
//     console.log(validValue)
//     console.log(!!validValue)
//     console.log(!!value)
//     if (validValue && !value){
//       console.log(value)
//       callback(new Error(warning));
//     } else {
//       callback();
//     }
//   }
// }
// flow控制面板取消刷新页面
function preventUpdatePage(e){
  e.preventDefault()
  return false;
}
// 消除联级选择器的cpu飙升bug
function cascaderVisibleChange(){
  nextTick(() => {
    let $el = document.querySelectorAll('.el-cascader-panel .el-cascader-node[aria-owns]');
    Array.from($el).forEach(item => {
      item.removeAttribute('aria-owns');
    });
  })
}
// id生成器
function getId(){
  return new Promise((resolve, reject) => {
    createId()
      .then(res => {
        resolve(res);
      })
      .catch(err => {
        reject(err)
      })
  });
}
// 抻平数组
function flatArr(arr, key){
  let result = [];
  arr.forEach(item => {
    result.push(item);
    if (item[key] && Array.isArray(item[key])){
      result.push(flatArr(item[key]))
    }
  });
  return result.flat(Infinity);
}
function setCondition(arr){
  let res = [];
  arr.forEach(item => {
    item.key = parseInt(Math.random() * 1000).toFixed(0);
    res.push(item);
    if (Array.isArray(item.condition) && item.condition.length > 0){
      item.condition = setCondition(item.condition);
    }
  });
  return res;
}
// 组装步骤选择数组
// function getStepOptions(){
//   stepOptions = nodes.value.map(node => {
//     let children = [];
//     if (Array.isArray(node.algoExecStrategyOpts) && node.algoExecStrategyOpts.length > 0){
//       node.algoExecStrategyOpts.forEach(opt => {
//         children.push({
//           id: opt.id,
//           name: optName
//         });
//       });
//     }
//     return {
//       id: node.id,
//       name: node.name,
//       children
//     };
//   });
//   return stepOptions;
// }
// 添加步骤中选项回调 - 模块库/参数关联选项数组
function addOptForRelate(stepId, opt){
  dataForm.value.algoExecStrategyModuleLibs.forEach(item => {
    if (item.relateStepId.includes(stepId)){
      let stepResult = item.optsOfStep.find(step => step.id === stepId);
      stepResult.children.push({
        id: opt.id,
        name: opt.optName
      });
    }
  });
  dataForm.value.algoExecStrategyParams.forEach(item => {
    if (item.relateStepId.includes(stepId)){
      let stepResult = item.optsOfStep.find(step => step.id === stepId);
      stepResult.children.push({
        id: opt.id,
        name: opt.optName
      });
    }
  });
}
// 删除步骤中选项回调 - 模块库/参数关联选项数组
function delOptForRelate(stepId, optId){
  dataForm.value.algoExecStrategyModuleLibs.forEach(item => {
    if (item.relateStepId.includes(stepId)){
      let stepRes = item.optsOfStep.find(step => step.id === stepId);
      let optChildIndex = stepRes.children.findIndex(opt => opt.id === optId);
      stepRes.children.splice(optChildIndex, 1);
    }
    if (item.optIdSelect.includes(optId)){
      let optIdIndex = item.optIdSelect.findIndex(opt => opt === optId);
      item.optIdSelect.splice(optIdIndex, 1);
      item.relateOptId = item.optIdSelect.join(',');
    }
  });
  dataForm.value.algoExecStrategyParams.forEach(item => {
    if (item.relateStepId.includes(stepId)){
      let stepRes = item.optsOfStep.find(step => step.id === stepId);
      let optChildIndex = stepRes.children.findIndex(opt => opt.id === optId);
      stepRes.children.splice(optChildIndex, 1);
    }
    if (item.optIdSelect.includes(optId)){
      let optIdIndex = item.optIdSelect.findIndex(opt => opt === optId);
      item.optIdSelect.splice(optIdIndex, 1);
      item.paramsSourceOptId = item.optIdSelect.join(',');
    }
  });
}
// 删除步骤回调 - 模块库/参数关联选项数组
function delStepForRelate(stepId, stepObj){
  new Promise((resolve, reject) => {
    dataForm.value.algoExecStrategyModuleLibs.forEach(item => {
      if (item.relateStepId.includes(stepId)){
        let stepSelectIndex = item.relateStepId.findIndex(step => step === stepId);
        item.relateStepId.splice(stepSelectIndex, 1);
        let optsStepInd = item.optsOfStep.findIndex(optStep => optStep.id === stepId);
        item.optsOfStep.splice(optsStepInd, 1);
        stepObj.algoExecStrategyOpts.forEach(opt => {
          if (item.optIdSelect.includes(opt.id)){
            let optIndex = item.optIdSelect.findIndex(oId => oId === opt.id);
            item.optIdSelect.splice(optIndex, 1);
          }
        });
        item.relateOptId = item.optIdSelect.join(',');
      }
    });
    resolve();
  });
  new Promise((resolve, reject) => {
    dataForm.value.algoExecStrategyParams.forEach(item => {
      if (item.relateStepId.includes(stepId)){
        let stepSelectIndex = item.relateStepId.findIndex(step => step === stepId);
        item.relateStepId.splice(stepSelectIndex, 1);
        let optsStepInd = item.optsOfStep.findIndex(optStep => optStep.id === stepId);
        item.optsOfStep.splice(optsStepInd, 1);
        stepObj.algoExecStrategyOpts.forEach(opt => {
          if (item.optIdSelect.includes(opt.id)){
            let optIndex = item.optIdSelect.findIndex(oId => oId === opt.id);
            item.optIdSelect.splice(optIndex, 1);
          }
        });
        item.paramsSourceOptId = item.optIdSelect.join(',');
      }
    });
    resolve();
  });
  
}
// 初始化步骤视图数据
function initNodes(events){
  if (Array.isArray(events) && events.length > 0){
    nodes.value = events.map(item => {
      let node = deepCopy(defaultNode);
      let data = deepCopy(defaultStepData);
      data.id = item.id;
      data.name = item.name;
      data.description = item.description;
      node.position.x = +item.positionX;
      node.position.y = +item.positionY;
      data.algoExecStrategyOpts = [];
      if (Array.isArray(item.algoExecStrategyOpts) && item.algoExecStrategyOpts.length > 0){
        item.algoExecStrategyOpts.forEach(optItem => {
          data.algoExecStrategyOpts.push(Object.assign({}, optItem));
        });
        data.currentIndex = data.algoExecStrategyOpts.length > 5 ? 4 : (data.algoExecStrategyOpts.length - 1);
      }
      data.type = item.type;
      switch (data.type){
        case api.strategy.stepType.START:
          node.type = api.strategy.nodeType.START;
          break;
        case api.strategy.stepType.STEP:
          node.type = api.strategy.nodeType.STEP;
          break;
        case api.strategy.stepType.END:
          node.type = api.strategy.nodeType.END;
          break;
      }
      node.data = data;
      node.id = item.id;
      return node;
    });
    // getStepOptions();
  } else {
    nodes.value = [];
  }
}
// 初始化关系视图数据
function initEdges(flows){
  if (Array.isArray(flows) && flows.length > 0){
    edges.value = flows.map(item => {
      let edge = deepCopy(defaultEdge);
      let data = deepCopy(defaultEdgeData);
      data.sourceRefId = item.sourceRefId;
      data.targetRefId = item.targetRefId;
      data.id = item.id;
      data.relation = item.relation;
      if (Array.isArray(item.condition) && item.condition.length > 0){
        data.condition = setCondition(item.condition);
      } else {
        data.condition = [];
      }
      if (data.condition.length > 0){
        edge.animated = true;
      }
      edge.id = item.id;
      edge.source = item.sourceRefId;
      edge.target = item.targetRefId;
      edge.sourceNode = nodes.value.find(n => n.id === item.sourceRefId);
      edge.targetNode = nodes.value.find(n => n.id === item.targetRefId);
      edge.data = data;
      return edge;
    });
  } else {
    edges.value = [];
  }
}
// 初始化模块库数组
function initModuleLibs(moduleLibs, steps){
  if (Array.isArray(moduleLibs) && moduleLibs.length > 0){
    dataForm.value.algoExecStrategyModuleLibs = moduleLibs.map(item => {
      let moduleLibItem = Object.assign({}, item);
      moduleLibItem.key = parseInt(Math.random() * 1000).toFixed(0);
      moduleLibItem.rules = {
        moduleLibId: rule.createRequiredRule('请选择对应的模块库'),
        isRelateOpt: rule.createRequiredRule('请选择是否关联选项')
      };
      moduleLibItem.formRef = null;
      if (item.isRelateOpt === 1 && typeof item.relateOptId === 'string'){
        moduleLibItem.rules.relateOptId = rule.createRequiredRule('请选择要关联的选项');
        moduleLibItem.optIdSelect = item.relateOptId.split(',');
        moduleLibItem.relateStepId = [];
        moduleLibItem.optsOfStep = [];
        moduleLibItem.optIdSelect.forEach(optId => {
          let stepResult = steps.find(step => {
            let optResult = step.algoExecStrategyOpts.find(opt => opt.id === optId);
            if (optResult && !moduleLibItem.relateStepId.includes(step.id)){
              moduleLibItem.relateStepId.push(step.id);
              return step;
            }
          });
          if (stepResult){
            let children = stepResult.algoExecStrategyOpts.map(opt => ({
              id: opt.id,
              name: opt.optName
            }));
            moduleLibItem.optsOfStep.push({
              id: stepResult.id,
              name: stepResult.name,
              children
            });
          }
        });
        // moduleLibOpts.forEach(optId => {
        //   let stepResult = steps.find(step => {
        //     let optResult = step.algoExecStrategyOpts.find(opt => opt.id === optId);
        //     if (optResult){
        //       return step;
        //     }
        //   });
        //   stepResult && stepResult.id && moduleLibItem.optIdSelect.push([stepResult.id, optId]);
        // });
      }
      return moduleLibItem;
    });
  } else {
    dataForm.value.algoExecStrategyModuleLibs = [];
  }
}
// 初始化参数
function initParams(params, steps){
  let timenow = Date.now();
  if (Array.isArray(params) && params.length > 0){
    dataForm.value.algoExecStrategyParams = params.map(item => {
      let paramsItem = Object.assign({}, item);
      paramsItem.key = parseInt(Math.random() * 1000).toFixed(0);
      paramsItem.rules = {
        paramsSource: rule.createRequiredRule('请选择参数源'),
        paramsCode: rule.createRequiredRule('请输入参数编码'),
        paramsType: rule.createRequiredRule('请选择参数类型'),
        paramsValue: rule.createRequiredRule('请输入参数值')
      };
      paramsItem.formRef = null;
      if (item.paramsSource === 0 && typeof item.paramsSourceOptId === 'string'){
        paramsItem.rules.paramsSourceOptId = rule.createRequiredRule('请选择要关联的选项');
        paramsItem.optIdSelect = item.paramsSourceOptId.split(',');
        paramsItem.relateStepId = [];
        paramsItem.optsOfStep = [];
        paramsItem.optIdSelect.forEach(optId => {
          let stepResult = steps.find(step => {
            let optResult = step.algoExecStrategyOpts.find(opt => opt.id === optId);
            if (optResult && !paramsItem.relateStepId.includes(step.id)){
              paramsItem.relateStepId.push(step.id);
              return step;
            }
          });
          if (stepResult){
            let children = stepResult.algoExecStrategyOpts.map(opt => ({
              id: opt.id,
              name: opt.optName
            }));
            paramsItem.optsOfStep.push({
              id: stepResult.id,
              name: stepResult.name,
              children
            });
          }
        });

        // paramsSourceOpts.forEach(optId => {
        //   let stepResult = steps.find(step => {
        //     let optResult = step.algoExecStrategyOpts.find(opt => opt.id === optId);
        //     if (optResult){
        //       return step;
        //     }
        //   });
        //   stepResult && stepResult.id && paramsItem.optIdSelect.push([stepResult.id, optId]);
        // });
      }
      return paramsItem;
    })
    timenow = (Date.now() - timenow) / 1000
  } else {
    dataForm.value.algoExecStrategyParams = [];
  }
}

// ============> methods
instance.onInit(() => {
  instance.fitView();
});
// 初始化
function init(){
  getStrategyDetail({id: route.query.id})
    .then(res => {
      Object.keys(res).forEach(key => {
        if (!Array.isArray(res[key]) && key !== 'id'){
          dataForm.value[key] = res[key];
        }
      })
      defaultStepData.strategyId = res.id;
      defaultEdgeData.strategyId = res.id;
      defaultModuleLib.strategyId = res.id;
      defaultParams.strategyId = res.id;
      uploadObj.value.exampleFileId.fileName = dataForm.value.exampleFileId ? res.exampleFileName : '';
      // 初始化步骤数组
      initNodes(res.algoExecStrategyEvents);
      initEdges(res.algoExecStrategySequenceFlows);
      // 初始化参数数组
      initParams(res.algoExecStrategyParams, res.algoExecStrategyEvents);
      initModuleLibs(res.algoExecStrategyModuleLibs, res.algoExecStrategyEvents);
      dataForm.value.id = res.id;
    })
}
// 点击控制面板的添加步骤
async function createNode(){
  let id;
  try {
    id = await getId();
  } catch(err){
    console.log(err)
    return;
  }
  let x = nodes.value.length > 0 ? nodes.value.at(-1).position.x + 200 : 50;
  let y = nodes.value.length > 0 ? nodes.value.at(-1).position.y : 50;
  let data = deepCopy(defaultStepData);
  data.id = id;
  let node = deepCopy(defaultNode);
  node.data = data;
  node.id = id;
  node.position.x = x;
  node.position.y = y;
  defaultOption.eventId = id;
  nodeDialoger.value.title = '添加步骤';
  nodeDialoger.value.node = node;
  nodeDialoger.value.flag = true;
}
// 全部清空
function clearAll(){
  ElMessageBox.confirm('您是否确认清除所有步骤及关系以及所有关联选项的配置？', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消'
  })
    .then(() => {
      nodes.value = [];
      edges.value = [];
      dataForm.value.algoExecStrategyModuleLibs.forEach(item => {
        item.relateOptId = '';
        item.relateStepId = [];
        item.optsOfStep = [];
        item.optIdSelect = [];
      });
      dataForm.value.algoExecStrategyParams.forEach(item => {
        item.paramsSourceOptId = '';
        item.relateStepId = [];
        item.optsOfStep = [];
        item.optIdSelect = [];
      });
    })
    .catch(() => {})
}
// 点击步骤的设置按钮
function setStep(item){
  let nodeObj = nodes.value.find(node => node.id === item.id);
  nodeDialoger.value.title = '编辑步骤';
  nodeDialoger.value.node = nodeObj;
  defaultOption.eventId = item.id;
  nodeDialoger.value.flag = true;
}
// 点击步骤的删除按钮
function delStep(item){
  ElMessageBox.confirm('您是否确认删除此步骤及其所有关系？', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消'
  })
    .then(() => {
      let connectEdges = getConnectedEdges(item.id, edges.value);
      let delNodeIndex = nodes.value.findIndex(node => node.id === item.id);
      if (connectEdges.length > 0){
        connectEdges.forEach(edge => {
          let delIndex = edges.value.findIndex(item => item.id === edge.id);
          edges.value.splice(delIndex, 1);
        })
      }
      delStepForRelate(item.data.id, item.data);
      nodes.value.splice(delNodeIndex, 1);

    })
    .catch(() => {})
}
// 输入创建选项
async function createStepOption(optionName){
  let result = nodeDialoger.value.node.data.algoExecStrategyOpts.find(item => item.optName === optionName);
  if (result){
    ElMessage.warning('已存在该名称的选项，请重新输入');
    return;
  }
  if (optionName != '' && optionName != undefined && optionName != null) {
    let id;
    try {
      id = await getId();
    } catch(err){
      console.log(err)
      throw new Error('已存在该名称的选项，请重新输入');
    }
    let optionObj = Object.assign({}, defaultOption);
    optionObj.id = id;
    optionObj.optName = optionName;
    nodeDialoger.value.node.data.algoExecStrategyOpts.push(optionObj);
    addOptForRelate(nodeDialoger.value.node.data.id, optionObj);
    nodeDialoger.value.node.data.optionInput = '';
    let optionLength = nodeDialoger.value.node.data.algoExecStrategyOpts.length;
    nodeDialoger.value.node.data.currentIndex = optionLength > 5 ? 4 : (optionLength - 1);
  } else {
    ElMessage.warning('选项名称不能为空， 请重新输入')
  }
}
// 点击删除选项
function delOption(item, index){
  nodeDialoger.value.node.data.algoExecStrategyOpts.splice(index, 1);
  let optionLength = nodeDialoger.value.node.data.algoExecStrategyOpts.length;
  nodeDialoger.value.node.data.currentIndex = optionLength > 5 ? 4 : (optionLength - 1);
  delOptForRelate(nodeDialoger.value.node.data.id, item.id);
}
// 修改步骤的类型事件
function changeStepType(e){
  let result = nodes.value.find(item => item.type === api.strategy.nodeType.START);
  if (e === api.strategy.stepType.START && result){
    ElMessage.warning('起始步骤只能存在一个，当前已存在起始步骤，请核对！');
    nodeDialoger.value.node.data.type = null;
    return;
  }
  switch (e){
    case api.strategy.stepType.START:
      nodeDialoger.value.node.type = api.strategy.nodeType.START;
      break;
    case api.strategy.stepType.STEP:
      nodeDialoger.value.node.type = api.strategy.nodeType.STEP;
      break;
    case api.strategy.stepType.END:
      nodeDialoger.value.node.type = api.strategy.nodeType.END;
      break;
  }
}
// 点击步骤选项的上箭头
function intoViewTop(item){
  if (item.data.currentIndex > 4){
    let nextOpt = document.getElementById(`${item.id}opt${item.data.currentIndex - 5}`);
    let optionsDom = nextOpt.parentElement;
    // console.dir(nextOpt)
    optionsDom.scrollTo({
      top: 25 * (item.data.currentIndex - 5),
      behavior: 'smooth'
    });
    item.data.currentIndex--;
    nextOpt = null;
  }
}
// 点击步骤选项的下箭头
function intoViewBottom(item){
  if (item.data.currentIndex < (item.data.algoExecStrategyOpts.length - 1)){
    let nextOpt = document.getElementById(`${item.id}opt${item.data.currentIndex + 1}`);
    let optionsDom = nextOpt.parentElement;
    // console.dir(nextOpt)
    optionsDom.scrollTo({
      top: 25 * (item.data.currentIndex - 3),
      behavior: 'smooth'
    });
    item.data.currentIndex++;
    nextOpt = null;
  }
}
// 步骤弹框确认事件
function handleNode(){
  let findResult = nodes.value.find(item => item.id === nodeDialoger.value.node.id);
  nodeDiaForm.value.validate(valid => {
    if (valid){
      if (!findResult){
        nodes.value.push(nodeDialoger.value.node);
        ElMessage.success('添加步骤成功！');
        nodeDialoger.value.node = null;
        nodeDialoger.value.flag = false;
      } else {
        nodeDialoger.value.flag = false;
        nodeDialoger.value.node = null;
      }
    } else {
      ElMessage.warning('提交信息验证失败，请核对后提交');
    }
  })
}
// 步骤弹框取消事件
function handleNodeCancel(){
  let findResult = nodes.value.find(item => item.id === nodeDialoger.value.node.id);
  if (!findResult) {
    nodeDialoger.value.flag = false;
    nodeDialoger.value.node = null;
  } else {
    nodeDiaForm.value.validate(valid => {
      if (valid){
        nodeDialoger.value.flag = false;
        nodeDialoger.value.node = null;
      } else {
        ElMessage.warning('当前修改信息验证失败，请核对');
      }
    })
  }
  
}

// ============> 边
// 控制面板的清除所有关系
function delAllEdge(){
  ElMessageBox.confirm('您是否确认清除所有关系？', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消'
  })
    .then(() => {
      edges.value = [];
    })
    .catch(() => {})
}
// 边的连接事件
instance.onConnect(async (e) => {
  let id;
  try {
    id = await getId();
  } catch(err){
    console.log(err);
    return;
  }
  let edge = deepCopy(defaultEdge);
  let data = deepCopy(defaultEdgeData);
  edge.id = id;
  data.id = id;
  edge.source = e.source;
  edge.target = e.target;
  data.sourceRefId = e.source;
  data.targetRefId = e.target;
  let sourceNode = nodes.value.find(item => item.id == e.source);
  let targetNode = nodes.value.find(item => item.id == e.target);
  edge.sourceNode = sourceNode;
  edge.targetNode = targetNode;
  edge.data = data;
  edgeDialoger.value.title = '添加关系';
  edgeDialoger.value.otherBtn.show = false;
  edgeDialoger.value.edge = edge;
  edgeDialoger.value.flag = true;
});
instance.onEdgeDoubleClick((e) => {
  let edgeObj = edges.value.find(item => e.edge.id === item.id);
  edgeDialoger.value.title = '编辑关系';
  edgeDialoger.value.edge = edgeObj;
  edgeDialoger.value.otherBtn.show = true;
  edgeDialoger.value.flag = true;
})
// 边弹框中点击添加事件
function addCondition(){
  let condition = deepCopy(defaultCondition);
  condition.key = parseInt(Math.random() * 1000).toFixed(0);
  edgeDialoger.value.edge.data.condition.push(condition);
}
// 边弹框condition的一级组件发射的改变值事件
function changeConditionItem(item, event){
  item.propId = event.propId;
  item.value = event.value;
}
// 边弹框condition的一级组件发射的operator关系选择事件
function changeConditionItemOper(item, value){
  item.operator = value;
}
// 边弹框condition的一级组件发射的relation选择事件
function changeConditionItemRelation(item, value){
  item.relation = value;
}
// 变弹框condtion的一级组件发射的删除该项事件
function delConditionItem(index){
  edgeDialoger.value.edge.data.condition.splice(index, 1);
}
// 边弹框点击删除当前关系
function delCurrentEdge(){
  ElMessageBox.confirm('您是否确认删除当前关系？', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消'
  })
    .then(() => {
      let currentIndex = edges.value.findIndex(item => item.id === edgeDialoger.value.edge.id);
      edgeDialoger.value.flag = false;
      edgeDialoger.value.edge = null;
      edges.value.splice(currentIndex, 1);
      ElMessage.success('删除成功');
    })
    .catch(() => {})
}
// 边弹框的确认事件
function handleEdge(){
  let conditionResult = flatArr(edgeDialoger.value.edge.data.condition, 'condition');
  // 判断operator
  let operatorFlag = false;
  let valueFlag = false;
  let relationFlag = false;
  conditionResult.forEach(item => {
    if (!item.operator){
      operatorFlag = true;
    }
    if (!item.value){
      valueFlag = true;
    }
    if (Array.isArray(item.condition) && item.condition.length > 0 && !item.relation){
      relationFlag = true;
    }
  });
  if (Array.isArray(edgeDialoger.value.edge.data.condition) && edgeDialoger.value.edge.data.condition.length > 0 && !edgeDialoger.value.edge.data.relation){
    relationFlag = true;
  }
  if (operatorFlag || relationFlag){
    ElMessage.warning('请完成所有关系的描述');
    return;
  }
  if (valueFlag){
    ElMessage.warning('请完成所有关系所关联的选项');
    return;
  }
  let currentEdge = edges.value.find(item => item.id === edgeDialoger.value.edge.id);
  if (Array.isArray(edgeDialoger.value.edge.data.condition) && edgeDialoger.value.edge.data.condition.length > 0){
    edgeDialoger.value.edge.animated = true;
  }
  if (!currentEdge){
    ElMessage.success('添加关系成功');
    edges.value.push(edgeDialoger.value.edge);
    edgeDialoger.value.flag = false;
    edgeDialoger.value.edge = null;
  } else {
    edgeDialoger.value.flag = false;
    edgeDialoger.value.edge = null;
  }
}
// 边弹框的取消事件
function handleEdgeCancel(){
  let currentEdge = edges.value.find(item => item.id === edgeDialoger.value.edge.id);
  if (!currentEdge){
    edgeDialoger.value.flag = false;
    edgeDialoger.value.edge = null;
  } else {
    let conditionResult = flatArr(edgeDialoger.value.edge.data.condition, 'condition');
    // 判断operator
    let operatorFlag = false;
    let valueFlag = false;
    let relationFlag = false;
    conditionResult.forEach(item => {
      if (!item.operator){
        operatorFlag = true;
      }
      if (!item.value){
        valueFlag = true;
      }
      if (Array.isArray(item.condition) && item.condition.length > 0 && !item.relation){
        relationFlag = true;
      }
    });
    if (Array.isArray(edgeDialoger.value.edge.data.condition) && edgeDialoger.value.edge.data.condition.length > 0 && !edgeDialoger.value.edge.data.relation){
      relationFlag = true;
    }
    if (operatorFlag || relationFlag){
      ElMessage.warning('请完成所有关系的描述');
      return;
    }
    if (valueFlag){
      ElMessage.warning('请完成所有关系所关联的选项');
      return;
    }
    edgeDialoger.value.flag = false;
    edgeDialoger.value.edge = null;
  }
  
}

// ============> 模块库部分
const stepOptions = computed(() => {
  return nodes.value.map(item => {
    let result = {
      id: item.id,
      name: item.data.name,
      children: []
    };
    item.data.algoExecStrategyOpts.forEach(opt => {
      result.children.push({id: opt.id, name: opt.optName, children: []});
    });
    return result;
  });
});
// let stepOptions = [];

// 获取模块库列表
function getModuleLibs(){
  moduleLibApi.getModuleLibs()
    .then(res => {
      if (res && Array.isArray(res) && res.length > 0){
        moduleLibDatas.value = res;
        // moduleLibDatas = res;
      }
    })
}
// 添加模块库配置
function addModuleLib(){
  let moduleLibItem = deepCopy(defaultModuleLib);
  moduleLibItem.key = parseInt(Math.random() * 1000).toFixed(0);
  dataForm.value.algoExecStrategyModuleLibs.push(moduleLibItem);
}
// 删除模块库配置
function handleDelModuleLib(item, index){
  dataForm.value.algoExecStrategyModuleLibs.splice(index, 1);
}
// 绑定模块库配置的表单
function bindModuleLibRef(item){
  return function (dom){
    if (dom){
      item.formRef = dom;
    }
  }
}
// 选择是否关联选项
function isRelateChange(item, index){
  if (item.isRelateOpt === 1){
    item.rules.relateOptId = rule.createRequiredRule('请选择要关联的选项');
  } else {
    item.rules.relateOptId = null;
    item.optIdSelect = [];
    item.optsOfStep = [];
    item.relateStepId = [];
    item.relateOptId = '';
  }
  /*
  if (item.paramsSource === 0){
    item.rules.paramsSourceOptId = rule.createRequiredRule('请选择要关联的选项');
  } else {
    item.rules.paramsSourceOptId = null;
    item.optIdSelect = [];
    item.optsOfStep = [];
    item.paramsSourceOptId = '';
    item.relateStepId = [];
  }
  */
}
// 选择模块库事件
function selectModuleLibs(item, e){
  if (e && Array.isArray(e) && e.length > 0) {
    item.moduleLibId = e.at(-1);
  } else {
    item.moduleLibId = null;
  }
}
// 模块库/参数选择关联步骤事件
function moduleLibSelectStepId(item, e){ 
  item.optIdSelect = [];
  if (Array.isArray(e) && e.length > 0){
    item.optsOfStep = e.reduce((options, stepId) => {
      options.push(stepOptions.value.find(step => step.id === stepId));
      return options;
    }, []);
  } else {
    item.optsOfStep = [];
  }
}
// 模块库/参数选择关联选项事件
function moduleLibSelectOptId(item, key, e){
  if (Array.isArray(e) && e.length > 0){
    item[key] = e.join(',');
  } else {
    item[key] = '';
  }
  // if (e.length > 0){
  //   item.relateOptId = e.reduce((relateOptIds, currentOpts) => {
  //     relateOptIds.push(currentOpts.at(-1));
  //     return relateOptIds;
  //   }, []).join(',');
  // } else {
  //   item.relateOptId = ''
  // }
}

// ============> 参数部分
function addParams(){
  let paramsItem = deepCopy(defaultParams);
  paramsItem.key = parseInt(Math.random() * 1000).toFixed(0);
  dataForm.value.algoExecStrategyParams.push(paramsItem);
}
// 删除参数配置
function handleDelParams(item, index){
  dataForm.value.algoExecStrategyParams.splice(index, 1);
}
// 选择参数源
function paramsSourceChange(item, index){
  if (item.paramsSource === 0){
    item.rules.paramsSourceOptId = rule.createRequiredRule('请选择要关联的选项');
  } else {
    item.rules.paramsSourceOptId = null;
    item.optIdSelect = [];
    item.optsOfStep = [];
    item.paramsSourceOptId = '';
    item.relateStepId = [];
  }
}
// 参数选择关联选项
function paramsSelectOptId(item, e){
  if (e.length > 0){
    item.paramsSourceOptId = e.reduce((paramsSourceOptIds, currentOpts) => {
      paramsSourceOptIds.push(currentOpts.at(-1));
      return paramsSourceOptIds;
    }, []).join(',');
  } else {
    item.paramsSourceOptId = ''
  }
}

// ============> all
function validCreateForm(){
  return new Promise((resolve, reject) => {
    createForm.value.validate(valid => {
      if (valid){
        resolve();
      } else {
        reject();
      }
    })
  })
}
function validParts(){
  let partsData = [...dataForm.value.algoExecStrategyModuleLibs, ...dataForm.value.algoExecStrategyParams];
  let promises = [];
  if (partsData.length < 1){
    return Promise.resolve();
  } else {
    partsData.forEach(item => {
      promises.push(new Promise((resolve, reject) => {
        item.formRef.validate(valid => {
          if (valid){
            resolve();
          } else {
            reject();
          }
        })
      }));
    });
    return Promise.all(promises)
  }

}
// 创建策略
function handleCreate(){
  if (dataForm.value.createFlag){
    ElMessage.warning('当前正在执行，请稍后');
    return;
  }
  createForm.value.validate(valid => {
    if (valid) {
      dataForm.value.createFlag = true;
      appStore.openLoading('策略任务创建中...');
      createStrategy(dataForm.value)
        .then(res => {
          if (res && res.id){
            ElMessage.success('策略任务创建成功，请继续配置！');
            dataForm.value.id = res.id;
            defaultStepData.strategyId = res.id;
            defaultEdgeData.strategyId = res.id;
            defaultModuleLib.strategyId = res.id;
            defaultParams.strategyId = res.id;
          } else {
            ElMessage.error('策略任务创建失败，请稍后重试或联系管理员');
          }
        })
        .catch(err => {
          console.log(err);
        })
        .finally(() => {
          dataForm.value.createFlag = false;
          appStore.closeLoading();
        })
    } else {
      ElMessage.warning('当前提交项填写信息有误，请核对后提交');
    }
  })
}
// 保存策略
async function handleUpdate(){
  if (dataForm.value.updateFlag){
    ElMessage.warning('当前正在执行，请稍后');
    return;
  }
  try {
    await validCreateForm();
    await validParts();
  } catch(err){
    ElMessage.warning('提交信息验证失败，请核对后提交');
    return;
  } finally {
    dataForm.value.showBasic = true;
    dataForm.value.showStep = true;
    dataForm.value.showModuleLib = true;
    dataForm.value.showParams = true;
  }
  dataForm.value.updateFlag = true;
  dataForm.value.algoExecStrategyEvents = nodes.value.map(item => {
    item.data.positionX = `${item.position.x}`;
    item.data.positionY = `${item.position.y}`;
    return item.data;
  });
  dataForm.value.algoExecStrategySequenceFlows = edges.value.map(item => item.data);
  appStore.openLoading('策略配置保存中...');
  try {
    console.log(dataForm.value)
    let res = await updateStrategy(dataForm.value);
    ElMessage.success('保存策略配置成功');
  } catch(err){
    console.log(err);
  } finally {
    dataForm.value.updateFlag = false;
    appStore.closeLoading();
  }
  // dataForm.value.showBasic = true;
  // dataForm.value.showStep = true;
  // createForm.value.validate(valid => {
  //   if (valid){
  //     dataForm.value.updateFlag = true;
  //     // appStore.openLoading('策略任务保存配置中...');
  //     //  algoExecStrategyEvents
  //     // algoExecStrategySequenceFlows
  //     console.log(nodes.value)
  //     console.log(edges.value)
  //     dataForm.value.algoExecStrategyEvents = nodes.value.map(item => item.data);
  //     dataForm.value.algoExecStrategySequenceFlows = nodes.value.map(item => item.data);
  //     updateStrategy(dataForm.value)
  //       .then(res => {

  //       })
  //   } else {
  //     ElMessage.warning('当前提交项填写信息有误，请核对后提交');
  //   }
  // })
}
function back(){
  router.back();
}

</script>
<style lang='scss' scoped>
@import '@/assets/styles/mixin.scss';
.data-show .data-title-between {
  @include flex-between-center;
  .data-title-actions {
    display: flex;
  }
}
.flow-container {
  width: 100%;
  height: calc(100vh - 420px);
  border: 2px solid var(--color-main);
  border-radius: 8px;
  box-shadow: inset 0 0 8px var(--color-main-8);
}
// vue-flow样式
::v-deep {
  .vue-flow__container {
    width: 100%;
    height: 100%;
  }
  .vue-flow__node {
    width: 200px;
    border: 1px solid var(--color-main);
    border-radius: 4px;
    background: var(--color-white-10);
    padding: 8px;
    box-shadow: 0 0 2px 1px var(--color-main-8);
    .inner {
      width: 100%;
      background: var(--color-white-10);
      border: 1px solid var(--color-main);
      box-shadow: inset 0 0 2px 1px var(--color-main-8);
      color: var(--color-main);
      .step-name {
        width: 100%;
        height: 30px;
        line-height: 30px;
        text-align: center;
        font-size: 16px;
        font-weight: bold;
        @include text-overflow-ellipsis;
      }
      .step-actions {
        width: 80%;
        margin: 0 auto;
        display: flex;
        align-items: center;
        justify-content: space-around;
        .step-action {
          width: 49%;
          height: 20px;
          line-height: 20px;
          text-align: center;
          border-radius: 4px;
          transition: all 0.25s linear;
          &.set {
            border: 1px solid var(--color-main);
            background-color: var(--color-white-10);
            &:hover {
              background-color: var(--color-main);
              color: var(--color-white-10);
            }
          }
          &.del {
            border: 1px solid var(--color-red);
            background-color: var(--color-white-10);
            color: var(--color-red);
            &:hover {
              background-color: var(--color-red);
              color: var(--color-white-10);
            }
          }
        }
      }
      .step-actions-scroll {
        margin-bottom: 10px;
      }
      .step-options {
        width: 80%;
        max-height: 130px;
        // height: 150px;
        margin: 5px auto;
        // border: 1px solid var(--color-main);
        overflow: hidden;
        .step-option-item {
          width: 100%;
          height: 20px;
          margin: 5px 0;
          border: 1px solid var(--color-main);
          color: var(--color-white-10);
          background-color: var(--color-main);
          text-align: center;
          line-height: 20px;
          border-radius: 4px;
        }
        .step-option-item.end {
          border: 1px solid var(--color-red);
          background-color: var(--color-red);
        }
      }
    }
    &.vue-flow__node-start {
      background: var(--color-main-8);
    }
    &.vue-flow__node-end .inner {
      background: var(--color-main-8);
      color: var(--color-white-10);
      .step-actions .step-action {
        &.set {
          border: 1px solid var(--color-white-10);
          background-color: var(--color-main);
          &:hover {
            background-color: var(--color-white-10);
            color: var(--color-main);
          }
        }
        &.del {
          border: 1px solid var(--color-white-10);
          background-color: var(--color-red);
          color: var(--color-white-10);
          &:hover {
            background-color: var(--color-white-10);
            color: var(--color-red);
          }
        }
      }
      .step-options .step-option-item {
        border: 1px solid var(--color-white-10);
        background-color: var(--color-white-10);
        color: var(--color-main);
      }
    }
  }
  .vue-flow__controls {
    box-shadow: 0 0 4px 2px var(--color-main-8);
    right: 0;
    left: unset;
    .vue-flow__controls-button {
      // color: rgb(87,59,138)!important;
      color: var(--color-main)!important;
    }
  }
  .flex-actions-container {
    height: 32px;
    box-shadow: 0 0 4px 2px var(--color-main-8);
    @include flex-all-center;
    .flow-action-btn {
      display: inline-block;
      background-color: var(--color-white-10);
      color: var(--color-main);
      width: 32px;
      height: 32px;
      line-height: 32px;
      text-align: center;
      cursor: pointer;
      transition: all 0.25s linear;
      &:hover {
        background-color: var(--color-main);
        color: var(--color-white-10);
      }
    }
  }
  .vue-flow__handle {
    width: 10px;
    height: 10px;
    border-radius: 0;
    border: 2px solid var(--color-main);
    background-color: var(--color-white-10);
    &.target {
      background-color: var(--color-main);
    }
  }
  .vue-flow__edge-path {
    // stroke: rgba(87,59,138);
    stroke: var(--color-main);
    stroke-width: 3;
  }
}
.data-list-content {
  width: calc(100% - 100px);
  margin-left: 100px;
  height: 200px;
  background-color: var(--color-white-10);
  border: 2px solid var(--color-gray-8);
  @include inset-shadow-gray-8;
  overflow-y: auto;
  overflow-x: hidden;
  @include scrollBar;
  .data-list-content-empty {
    width: 100%;
    height: 100%;
    background-color: var(--color-white-5);
    @include flex-all-center;
    flex-direction: column;
    // 无数据提示语
    .data-list-content-empty-text {
      color: var(--color-main-8);
      font-size: 28px;
    }
    // 无数据图标
    .data-list-content-empty-icon {
      color: var(--color-main-8);
      font-size: 80px;
    }
  }
  .data-list-content-inner .option-item {
    width: 95%;
    height: 40px;
    margin: 5px auto;
    // 为最右边定位的关闭按钮预留空间
    padding-right: 35px;
    display: flex;
    align-items: center;
    background-color: var(--color-gray-2);
    border: 1px solid var(--color-main-3);
    border-radius: 8px;
    position: relative;
    .option-name {
      // width: 40%;
      // margin: 0 10px;
      width: calc(30% - 20px);
      margin: 0 5px;
    }
    .option-sort {
      // width: 25%;
      width: calc(30% - 20px);
      margin: 0 5px;
      .el-input-number {
        width: 100%;
      }
    }
    .option-desc {
      width: calc(40% - 26px);
      margin: 0 5px;
    }
    .option-end {
      margin: 0 10px;
      &::v-deep .el-checkbox__inner {
        border-color: var(--color-main);
      }
      &::v-deep .el-checkbox__input.is-checked .el-checkbox__inner {
        background-color: var(--color-main);
      }
    }
    .option-close {
      position: absolute;
      right: 10px;
      top: 50%;
      transform: translateY(-50%);
      color: var(--color-red);
      font-size: 18px;
      font-weight: bolder;
      cursor: pointer;
    }
    &::v-deep .el-input__wrapper.is-focus {
      box-shadow: 0 0 0 1px var(--color-main) inset!important;
    }
  }
}
.edge-set {
  width: 100%;
  position: relative;
  border: 2px solid var(--color-main);
  border-radius: 4px;
  background-color: var(--color-white-10);
  box-shadow: inset 0 0 8px var(--color-main-8);
  padding: 20px 0 10px;
  margin-top: 20px;
  .edge-relations {
    position: absolute;
    top: -15px;
    left: 20px;
  }
  .relations {
    background-color: var(--color-white-10);
    border: 2px solid var(--color-main);
    border-radius: 10px;
    overflow: hidden;
    .relation-item {
      margin: 0;
      height: 30px;
      &::v-deep .el-radio__input {
        display: none;
      }
      &::v-deep .el-radio__label {
        display: inline-block;
        padding: 0;
        height: 30px;
        line-height: 30px;
        padding: 0 5px;
        color: var(--color-main);
        border: 1px solid var(--color-main-4);
        transition: all 0.25s linear;
      }
    }
    .relation-item.is-checked {
      &::v-deep .el-radio__label {
        color: var(--color-white-10);
        background-color: var(--color-main);
      }
    }
  }
  .edge-add {
    position: absolute;
    width: 60px;
      height: 30px;
      right: 20px;
      top:-15px;
      text-align: center;
      line-height: 26px;
      font-weight: bold;
      border: 2px solid var(--color-main);
      border-radius: 10px;
      background-color: var(--color-white-10);
      color: var(--color-main);
      cursor: pointer;
      transition: all 0.3s linear;
      &:hover {
        background-color: var(--color-main);
        color: var(--color-white-10);
      }
  }
  .condition-empty {
    width: 100%;
    height: 180px;
    @include flex-all-center;
    flex-direction: column;
    .data-empty {
      color: var(--color-main);
      font-size: 20px;
    }
    // 无数据图标
    .data-empty-icon {
      color: var(--color-main);
      font-size: 80px;
    }
  }
}
.constions-outer {
  margin: 0 5px;
}
.data-action-show {
  display: flex;
}
.moduleLib-container {
  padding: 20px;
  .moduleLib-empty {
    width: 100%;
    height: 180px;
    border: 2px solid var(--color-main);
    border-radius: 4px;
    background-color: var(--color-gray-5);
    @include inset-shadow-main-8;
    @include flex-all-center;
    flex-direction: column;
    .data-empty {
      color: var(--color-main);
      font-size: 20px;
    }
    // 无数据图标
    .data-empty-icon {
      color: var(--color-main);
      font-size: 80px;
    }
  }
  .module-item {
    width: 100%;
    position: relative;
    border: 2px solid var(--color-main);
    border-radius: 4px;
    background-color: var(--color-gray-2);
    @include inset-shadow-main-8;
    padding: 10px 0;
    margin-bottom: 28px;
    .module-item-title {
      position: absolute;
      width: 60px;
      height: 30px;
      background-color: var(--color-main);
      color: var(--color-white-10);
      text-align: center;
      line-height: 30px;
      font-weight: bold;
      top: -15px;
      left: 20px;
      border-radius: 10px;
    }
    .module-item-del {
      position: absolute;
      width: 60px;
      height: 30px;
      right: 20px;
      top:-15px;
      text-align: center;
      line-height: 26px;
      font-weight: bold;
      border: 2px solid var(--color-main);
      border-radius: 10px;
      background-color: var(--color-white-10);
      color: var(--color-main);
      cursor: pointer;
      transition: all 0.3s linear;
      &:hover {
        background-color: var(--color-red);
        color: var(--color-white-10);
        border: 2px solid var(--color-red);
      }
    }
  }
}
.upload {
  width: 100%;
  min-height: 120px;
  height: 120px;
  &::v-deep .el-upload {
    @include wh-100;
    // height: 100%!important;
    .el-upload-dragger {
      @include wh-100;
      border-color: var(--color-main);
      padding: 0;
      .upload-empty {
        @include wh-100;
        @include flex-all-center;
        flex-direction: column;
        .upload-icon {
          font-size: 30px;
          color: var(--color-gray-10);
        }
        .upload-des {
          color: var(--color-gray-10);
        }
      }
      .upload-content {
        @include wh-100;
        @include flex-all-center;
        flex-direction: column;
        .upload-icon {
          font-size: 30px;
          color: var(--color-main);
        }
        .upload-des {
          color: var(--color-main);
        }
      }
      .upload-content-files {
        @include wh-100;
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: center;
        overflow-y: auto;
        @include scrollBar;
        .upload-content-item {
          position: relative;
          width: 100px;
          height: 80px;
          margin: 15px 10px;
          border: 2px solid var(--color-main);
          border-radius: 8px;
          background-color: var(--color-main-9);
          @include flex-all-center;
          flex-direction: column;
          .upload-icon {
            font-size: 30px;
            color: var(--color-white-10);
          }
          .upload-des {
            display: inline-block;
            color: var(--color-white-10);
            width: 100%;
            text-align: center;
            @include text-overflow-ellipsis;
          }
          .upload-content-item-close {
            position: absolute;
            top: -8px;
            right: -8px;
            color: var(--color-white-10);
            font-size: 10px;
            width: 20px;
            height:20px;
            text-align: center;
            line-height: 20px;
            border-radius: 50%;
            background-color: red;
          }
        }
      }
    }
  }
  &::v-deep .el-upload-list > .el-upload-list__item.is-success {
    display: none;
  }
}
.parameter-des {
  color: var(--color-main);
  cursor: pointer;
  margin: 0 8px;
}
</style>